package yxy.apple.nio;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.traffic.ChannelTrafficShapingHandler;
import io.netty.handler.traffic.GlobalTrafficShapingHandler;

public abstract class Initializer extends ChannelInitializer<NioSocketChannel> {
	private static GlobalTrafficShapingHandler globalTrafficShaper = null;

	/**
	 * 设置全局流量整形器，不启用则传入null;
	 * 
	 * @param globalTrafficShapingHandler
	 */
	public static void setGlobalTrafficShaper(GlobalTrafficShapingHandler shaper) {
		Initializer.globalTrafficShaper = shaper;
	}

	public static GlobalTrafficShapingHandler globalTrafficShaper() {
		return globalTrafficShaper;
	}

	@Override
	protected void initChannel(NioSocketChannel channel) throws Exception {
		ChannelPipeline pipeline = channel.pipeline();
		LogLevel level = this.provideLogLevel(channel);
		if (level != null) {
			pipeline.addFirst(new LoggingHandler(level));
		}
		SslContext ssl = this.provideSslContext(channel);
		if (ssl != null) {
			pipeline.addLast(ssl.newHandler(channel.alloc()));
		}
		Coder coder = this.provideCoder(channel);
		if (coder != null) {
			coder.assemble(pipeline);
		}
		Handler handler = this.provideHandler(channel);
		if (handler != null) {
			pipeline.addLast(handler);
		}
		ChannelTrafficShapingHandler shaper = this.provideChannelTrafficShaper(channel);
		if (shaper != null) {
			pipeline.addFirst(shaper);
		}
		if (Initializer.globalTrafficShaper != null) {
			pipeline.addFirst(Initializer.globalTrafficShaper);
		}
	}

	/**
	 * 提供Channel的日志级别，不输出日志可返回null
	 * 
	 * @return
	 */
	protected abstract LogLevel provideLogLevel(NioSocketChannel channel) throws Exception;

	/**
	 * 提供SSL加密传输通道上下文，不开启加密可返回null
	 * 
	 * @return
	 */
	protected abstract SslContext provideSslContext(NioSocketChannel channel) throws Exception;

	/**
	 * 提供通道编码器，原则上不应该返回null
	 * 
	 * @return
	 */
	protected abstract Coder provideCoder(NioSocketChannel channel) throws Exception;

	/**
	 * 提供通道的处理器，原则上不应该返回null
	 * 
	 * @return
	 */
	protected abstract Handler provideHandler(NioSocketChannel channel) throws Exception;

	/**
	 * 提供流量整形器，整形器可以是多个，不启用整形器可返回null
	 * 
	 * @return
	 */
	protected abstract ChannelTrafficShapingHandler provideChannelTrafficShaper(NioSocketChannel channel)
			throws Exception;

}
